﻿using UnityEngine;
using System.Collections;
using System.Text;
using System;
using System.IO;
using System.Collections.Generic;

public class Gene
{
    // Genotype representation is just the Lsystem with production rules and start axiom
    public float Fitness { get; set; }   

    public GenoType GenoType { get; set; }
    public PhenoType PhenoType { get; set; }

    public int Id;
    public int ParentId;

    public Gene(int id)
    {
        this.Id = id;
        this.ParentId = -1;
        Randomize();
    }

    public void SaveToFile(int gen)
    {
        using (StreamWriter sw = new StreamWriter(@"Genes\" + Id + ".gene"))
        {
            sw.WriteLine("Id: " + Id);
            sw.WriteLine("Generation: " + gen);
            sw.WriteLine("Fitness: " + Fitness);
            sw.WriteLine("Axiom: " + GenoType.Axiom);
            List<char> keys = new List<char>(GenoType.ProductionRules.Keys);
            foreach (char key in keys)
            {
                sw.WriteLine(key + " -> " + GenoType.ProductionRules[key]);
            }
            sw.WriteLine("System: " + GenoType.System);
        }
    }

    public void SaveToCSV(int gen)
    {
        using (StreamWriter sw = new StreamWriter(@"Genes\Gene" + Id + ".csv"))
        {
            string rules = "{";
            List<char> keys = new List<char>(GenoType.ProductionRules.Keys);
            foreach (char key in keys)
            {
                rules += "[" + key + " -> " + GenoType.ProductionRules[key] + "], ";
            }
            rules = rules.Substring(0, rules.Length - 2);
            rules += "}";
            sw.WriteLine("\"Generation\";\"Id\";\"ParentId\";\"Fitness\";\"Axiom\";\"Production Rules\";\"System\"");
            sw.WriteLine(string.Format("\"{0}\";\"{1}\";\"{2}\";\"{3}\";\"{4}\";\"{5}\";\"{6}\"", gen, Id, ParentId,
                Fitness.ToString("0.00").Replace('.', ','), GenoType.Axiom, rules, GenoType.System));                        
        }
    }

    public void AppendCSV(int gen, string filename)
    {
        using (StreamWriter sw = new StreamWriter(filename, true))
        {
            string rules = "{";
            List<char> keys = new List<char>(GenoType.ProductionRules.Keys);
            foreach (char key in keys)
            {
                rules += "(" + key + " -> " + GenoType.ProductionRules[key] + "), ";
            }
            rules = rules.Substring(0, rules.Length - 2);
            rules += "}";
            sw.WriteLine(string.Format("\"{0}\";\"{1}\";\"{2}\";\"{3}\";\"{4}\";\"{5}\";\"{6}\"", gen, Id, ParentId,
                    Fitness.ToString("0.00").Replace('.', ','), GenoType.Axiom, rules, GenoType.System));
        }
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        Gene other = obj as Gene;
        if ((System.Object)other == null)
        {
            return false;
        }

        return this.Id.Equals(other.Id);
    }

    public Gene(GenoType genoType, int id, int parentId)
    {
        this.Id = id;
        this.ParentId = parentId;
        GenoType = new GenoType(genoType);
    }

    public void Randomize()
    {
        GenoType = new GenoType(3);
    }

    public void Mutate()
    {
        GenoType.Mutate();
    }

    public void Prepare()
    {
        GenoType.Prepare();
    }

    public void CreatePhenoType()
    {
        //PhenoType = new PhenoType(GenoType.System);
    }

    //public Gene[] Reproduce(Gene other)
    //{
    //    int crossover = Random.Range(1, 8);

    //    Gene first = new Gene();
    //    Gene second = new Gene();

    //    first.Chromosome = "";
    //    second.Chromosome = "";

    //    for (int i = 0; i < this.Chromosome.Length; i++)
    //    {
    //        if (i < crossover)
    //        {
    //            first.Chromosome += this.Chromosome[i];
    //            second.Chromosome += other.Chromosome[i];
    //        }
    //        else
    //        {
    //            first.Chromosome += other.Chromosome[i];
    //            second.Chromosome += this.Chromosome[i];
    //        }
    //    }
    //    return new Gene[] { first, second };
    //}
}
